﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using LibEBML.Common;
using VBFOOL.MediaPlayer.Core.Interface;

namespace VBFOOL.MediaPlayer.Codecs
{
    public class H264Codec : ICodecFilter
    {
        public IDictionary<MediaStreamAttributeKeys, string> GetCodecPrivateData(IDictionary<string, object> RawData)
        {
            //throw new NotImplementedException();
            Dictionary<MediaStreamAttributeKeys, string> att = new Dictionary<MediaStreamAttributeKeys, string>();
            att[MediaStreamAttributeKeys.VideoFourCC] = "H264";
            att[MediaStreamAttributeKeys.Width] = RawData["Width"].ToString();
            att[MediaStreamAttributeKeys.Height] = RawData["Height"].ToString();
            byte[] b = RawData["CodecPrivateData"] as byte[];
            att[MediaStreamAttributeKeys.CodecPrivateData] = GetCodecPrivateDataString(b);
            return att;
        }
        string GetCodecPrivateDataString(byte[] RawData)
        {
            byte[] b = RawData;
            if (b[0] != 0x01)
            {
                throw new ArgumentException("错误的CodecPrivate格式");
            }
            int mp = 5;
            byte x1f = 0x1f;
            NALULength = b[4] & 3 + 1;
            var nsps = b[5] & x1f;
            mp++;
            var lsps = b[6] * 256 + b[7];
            mp += 2;
            int ml = nsps * lsps;
            mp += ml;
            var npps = b[mp];
            var lpps = b[mp + 1] * 256 + b[mp + 2];
            int ml2 = npps * lpps;
            byte[] cpdata = new byte[ml + ml2 + 6];
            cpdata[2] = 1;
            Buffer.BlockCopy(b, 8, cpdata, 3, ml);
            cpdata[ml + 5] = 1;
            Buffer.BlockCopy(b, mp + 3, cpdata, ml + 6, ml2);
            FirstFrameHeader = cpdata;
            return BitConverter.ToString(cpdata).Replace("-", "");
        }
        int NALULength = 4;
        byte[] NALUSpliter = new byte[] { 0, 0, 1 };
        byte[] FirstFrameHeader = null;
        public bool SupportCodecID(string CodecID)
        {
            return CodecID.Trim() == @"V_MPEG4/ISO/AVC";
        }
        protected byte[] GetNALU(byte[] Buff, int offset)
        {
            byte[] b = new byte[NALULength];
            Buffer.BlockCopy(Buff, offset, b, 0, b.Length);
            var len2 = ElementFactory.ConvertVintToLong(b);
            b = new byte[len2];
            Buffer.BlockCopy(Buff, offset + NALULength, b, 0, b.Length);
            return b;
            //return len2;
        }

        public byte[] Translate(byte[] source, int offset, int count)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            int i2 = offset, i = count;
            while (i2 < i)
            {
                byte[] nalu = GetNALU(source, i2);
                ms.Write(NALUSpliter, 0, 3);
                ms.Write(nalu, 0, nalu.Length);
                i2 += (nalu.Length + NALULength);
            }
            ms.Position = 0;
            return ms.ToArray();
        }
    }
    public class AACCodec : ICodecFilter
    {

        public IDictionary<MediaStreamAttributeKeys, string> GetCodecPrivateData(IDictionary<string, object> RawData)
        {
            Dictionary<MediaStreamAttributeKeys, string> att = new Dictionary<MediaStreamAttributeKeys, string>();
            var chn = (int)RawData["Channels"];
            var feq = (decimal)RawData["SamplingFrequency"];
            byte[] b = RawData["CodecPrivateData"] as byte[];
            using (var ms = new System.IO.MemoryStream())
            {
                var w = new System.IO.BinaryWriter(ms);
                w.Write((short)0xff);
                w.Write((short)chn);
                w.Write((int)feq);
                w.Write((int)(chn * feq * 0x02 / 0x04));
                //w.Write((int)12000);
                w.Write((short)0x04);
                w.Write((short)0x10);
                w.Write((short)b.Length);
                w.Write(b);
                byte[] hd = ms.ToArray();
                att[MediaStreamAttributeKeys.CodecPrivateData] = BitConverter.ToString(hd).Replace("-", "");
                return att;
            }
        }

        public bool SupportCodecID(string CodecID)
        {
            //return false;
            return CodecID == @"A_AAC";
        }


        public byte[] Translate(byte[] source, int offset, int count)
        {
            byte[] b = new byte[count];
            Buffer.BlockCopy(source, offset, b, 0, count);
            return b;
        }
    }
}
